package com.loe.ui.view

import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Paint
import android.graphics.Typeface
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import android.widget.Button
import androidx.annotation.Keep
import com.loe.mvp.ext_app.color
import com.loe.mvp.ext_java.float
import com.loe.mvp.ext_view.addTextAfterListener
import com.loe.ui.*
import com.loe.ui.api.ButtonApi
import com.loe.ui.api.IUiView
import com.loe.ui.page.UiPage
import com.quickjs.JSArray
import com.quickjs.JSObject

@Keep
@SuppressLint("AppCompatCustomView")
open class UiButton : Button, IUiView
{
    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    {
        initXML(attrs)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    {
        initXML(attrs)
    }

    private fun initXML(attrs: AttributeSet)
    {
    }

    override val jsObject by lazy { ButtonApi(this).jsObject }

    override fun setUI(ui: JSObject, uiPage: UiPage?): View
    {
        // click
        ui.gotHasBoolean("isClick") { setClick(it) }
        // textColor
        if (ui.contains("textColor"))
        {
            setTextColor(ui.gotString("textColor").color)
        } else
        {
            setTextColor(context.color(R.color.textColor))
        }

        // gravity
        ui.gotHasGravity("gravity") { gravity = it }

        // isTextSelectable
        ui.gotHasBoolean("isTextSelectable") { setTextIsSelectable(it) }
        // hint
        ui.gotHasString("hint") { hint = it }
        // hintColor
        ui.gotHasString("hintColor") { setHintTextColor(it.color) }
        // minLines
        ui.gotHasInt("minLines") { minLines = it }
        // maxLines
        ui.gotHasInt("maxLines") { maxLines = it }
        // ellipsize
        ui.gotHasString("ellipsis") { ellipsize = TextUtils.TruncateAt.valueOf(it.toUpperCase()) }

        // bold
        ui.gotHasBoolean("bold") { setBold(it) }
        // italic
        ui.gotHasBoolean("italic") { setItalic(it) }
        // textStyle
        ui.gotHasString("textStyle") { setTextStyle(it) }

        // onText
        ui.gotHasFunction("onText")
        { callback ->
            setTextListener { callback.call(jsObject, JSArray(jsContext).push(it)) }
        }

        // textSize
        ui.gotHasString("textSize") { setTextSize(it) }

        // autoVisible
        ui.gotHasBoolean("autoVisible") { isAutoVisible = it }
        // text
        ui.gotHasString("text") { setAutoText(it) }

        return this
    }

    override var onSelect: (() -> Unit)? = null

    /******************************************* 其他 *******************************************/

    var isAutoVisible: Boolean = false

    fun setAutoText(s: String?)
    {
        if (isAutoVisible) visibility = if (s == null || s.trim().isEmpty()) GONE else VISIBLE
        text = s
    }

    fun setClick(isClick: Boolean)
    {
        isAlpha = isClick
        isClickable = isClick
    }

    private var isAlpha = false

    override fun setTextColor(color: Int)
    {
        if (isAlpha)
        {
            val states = arrayOfNulls<IntArray>(3)
            states[0] = intArrayOf(android.R.attr.state_enabled, -android.R.attr.state_pressed)
            states[1] = intArrayOf(android.R.attr.state_enabled, android.R.attr.state_pressed)
            states[2] = intArrayOf(-android.R.attr.state_enabled)
            val alphaColor = (0xe0 shl 24) + (color and 0xFFFFFF)
            setTextColor(ColorStateList(states, intArrayOf(color, alphaColor, alphaColor)))
        } else
        {
            super.setTextColor(color)
        }
    }

    private var onText: ((s: String) -> Unit)? = null

    private val addTextChanged by lazy {
        addTextAfterListener()
        {
            onText?.invoke(it)
        }
    }

    fun setTextListener(onText: (s: String) -> Unit)
    {
        this.onText = onText
        addTextChanged
    }

    /***************************************** 文本样式 ***************************************/

    fun setBold(bold: Boolean)
    {
        typeface = if (bold) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
    }

    fun setItalic(italic: Boolean)
    {
        setTypeface(Typeface.DEFAULT, if (italic) Typeface.ITALIC else Typeface.NORMAL)
    }

    fun setTextStyle(textStyle: String)
    {
        when (textStyle)
        {
            "bold" -> paint.flags = Paint.FAKE_BOLD_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG
            "delete" -> paint.flags = Paint.STRIKE_THRU_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG
            "under" -> paint.flags = Paint.UNDERLINE_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG
            // normal
            else -> paint.flags = Paint.ANTI_ALIAS_FLAG
        }
    }

    fun setTextSize(size: String)
    {
        if (size.endsWith("px"))
        {
            setTextSize(TypedValue.COMPLEX_UNIT_PX, size.replace("px", "").float)
        } else
        {
            setTextSize(TypedValue.COMPLEX_UNIT_DIP, size.float)
        }
    }
}